package com.samehope.ar.util;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

import cn.hutool.core.util.IdUtil;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.model.ObjectMetadata;
import com.qcloud.cos.model.PutObjectRequest;
import com.qcloud.cos.model.PutObjectResult;
import com.qcloud.cos.model.StorageClass;
import com.qcloud.cos.region.Region;
import com.samehope.ar.common.CommonResult;
import com.samehope.ar.constant.FileTypeEnum;
import com.tencent.cloud.CosStsClient;
import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import org.json.JSONObject;
import javax.annotation.PostConstruct;

/**
 * <p>
 * COS对象存储处理
 * </p>
 *
 * @author LD
 * @since 2020-1-13
 */
@Component
public class CosUtils {

    @Value("${tencent.cos.accessKey}")
    private String AccessKey;

    private static String accessKey;

    @Value("${tencent.cos.secretKey}")
    private String SecretKey;

    private static String secretKey;

    @Value("${tencent.cos.bucketName}")
    private String BucketName;

    private static String bucketName;

    @Value("${tencent.cos.region}")
    private String Region;

    private static String region;

    @Value("${tencent.cos.bucketUrl}")
    private String BucketUrl;

    private static String bucketUrl;

    @PostConstruct
    public void init() {
        accessKey = this.AccessKey;
        secretKey = this.SecretKey;
        bucketName = this.BucketName;
        region = this.Region;
        bucketUrl = this.BucketUrl;
    }

    public static Map<String, String> getCredential(){
        TreeMap<String, Object> config = new TreeMap<String, Object>();

        try {
            // 云 API 密钥 secretId
            config.put("secretId", accessKey);
            // 云 API 密钥 secretKey
            config.put("secretKey", secretKey);
            //若需要设置网络代理，则可以如下设置
//            if (properties.containsKey("https.proxyHost")) {
//                System.setProperty("https.proxyHost", properties.getProperty("https.proxyHost"));
//                System.setProperty("https.proxyPort", properties.getProperty("https.proxyPort"));
//            }

            // 临时密钥有效时长，单位是秒
            config.put("durationSeconds", 1800);

            // 换成你的 bucket
            config.put("bucket", bucketName);
            // 换成 bucket 所在地区
            config.put("region", region);

            // 这里改成允许的路径前缀，可以根据自己网站的用户登录态判断允许上传的具体路径，
            // 例子： a.jpg 或者 a/* 或者 * (使用通配符*存在重大安全风险, 请谨慎评估使用)
            config.put("allowPrefix", "*");

            // 密钥的权限列表。简单上传和分片需要以下的权限，其他权限列表请看 https://cloud.tencent.com/document/product/436/31923
            String[] allowActions = new String[] {
                    // 简单上传
                    "name/cos:PutObject",
                    // 表单上传
                    "name/cos:PostObject",
                    // 分片上传： 初始化分片
                    "name/cos:InitiateMultipartUpload",
                    // 分片上传： 查询 bucket 中未完成分片上传的UploadId
                    "name/cos:ListMultipartUploads",
                    // 分片上传： 查询已上传的分片
                    "name/cos:ListParts",
                    // 分片上传： 上传分片块
                    "name/cos:UploadPart",
                    // 分片上传： 完成分片上传
                    "name/cos:CompleteMultipartUpload"
            };
            config.put("allowActions", allowActions);
            // 请求临时密钥信息
            JSONObject credential = CosStsClient.getCredential(config);
            // 请求成功：打印对应的临时密钥信息
            int expiredTime = credential.getInt("expiredTime");
            JSONObject credentials = credential.getJSONObject("credentials");
            String tmpSecretId = credentials.getString("tmpSecretId");
            String tmpSecretKey = credentials.getString("tmpSecretKey");
            String sessionToken = credentials.getString("sessionToken");
            Map<String, String> map = new HashMap<String, String>();
            map.put("tmpSecretId",tmpSecretId);
            map.put("tmpSecretKey",tmpSecretKey);
            map.put("sessionToken",sessionToken);
            map.put("expiredTime",expiredTime+"");
            map.put("bucket", bucketName);
            map.put("region", region);
            map.put("bucketUrl", bucketUrl);
            return map;
        } catch (Exception e) {
            // 请求失败，抛出异常
            throw new IllegalArgumentException("no valid secret !");
        }
    }

    public static CommonResult upload(MultipartFile file, Integer fileType) {

        String url = null;
        String key = "";
        String[] fileNames = file.getOriginalFilename().split("\\.");
        if (SessionUtil.getCompanyId() != null) {
            key = key + SessionUtil.getCompanyId() + "/";
        }
        if (SessionUtil.getProjectId() != null) {
            key = key + SessionUtil.getProjectId() + "/";
        }
        if (FileTypeEnum.PIC.getCode().equals(fileType)) {
            key = key + "pic/" + IdUtil.randomUUID() + "." + fileNames[fileNames.length - 1];
            try {
                url = doUpload(file.getBytes(), key);
            } catch (Exception e) {
                e.printStackTrace();
                url = null;
            }

            if (url == null) {
                return CommonResult.failed("文件上传异常");
            }

        } else {
            String fileName = IdUtil.randomUUID();
            String picKey = key;
            key = key + "video/" + fileName + "." + fileNames[fileNames.length - 1];
            try {
                url = doUpload(file.getBytes(), key);
            } catch (Exception e) {
                e.printStackTrace();
                url = null;
            }

            if (url == null) {
                return CommonResult.failed("文件上传异常");
            }


            // 缩略图保存
            String picUrl = null;
            try {
                String fetchPic = VideoUtils.fetchPic(file);
                picKey = picKey + "video/" + fileName + ".jpg";
                picUrl = doUpload(Base64.decodeBase64(fetchPic), picKey);
            } catch (Exception e) {
                e.printStackTrace();
            }
            if (picUrl == null) {
                return CommonResult.failed("文件上传异常");
            }
        }
        return CommonResult.success(url);
    }

    private static String doUpload(byte[] bytes, String key) {
        // 1 初始化用户身份信息(secretId, secretKey)
        COSCredentials cred = new BasicCOSCredentials(accessKey, secretKey);
        // 2 设置bucket的区域, COS地域的简称请参照 https://www.qcloud.com/document/product/436/6224
        ClientConfig clientConfig = new ClientConfig(new Region(region));
        // 3 生成cos客户端
        COSClient cosclient = new COSClient(cred, clientConfig);

        try {
            InputStream input = new ByteArrayInputStream(bytes);
            ObjectMetadata objectMetadata = new ObjectMetadata();
            // 从输入流上传必须制定content length, 否则http客户端可能会缓存所有数据，存在内存OOM的情况
            objectMetadata.setContentLength(bytes.length);
            // 默认下载时根据cos路径key的后缀返回响应的contenttype, 上传时设置contenttype会覆盖默认值
            //objectMetadata.setContentType("image/png");

            PutObjectRequest putObjectRequest =
                    new PutObjectRequest(bucketName, key, input, objectMetadata);
            // 设置存储类型, 默认是标准(Standard), 低频(standard_ia)
            putObjectRequest.setStorageClass(StorageClass.Standard);

            PutObjectResult putObjectResult = cosclient.putObject(putObjectRequest);
            // putobjectResult会返回文件的etag
            String etag = putObjectResult.getETag();
            return bucketUrl + key;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 关闭客户端
            cosclient.shutdown();
        }
        return null;
    }


}
